package com.teaphy.demo;

import com.teaphy.annotations.Author;
import com.teaphy.data.Student;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;

public class ConstructorDemo {
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		
		Class clz = Student.class;
		Constructor[] clzConstructors = clz.getConstructors();
		
		for (Constructor constructor : clzConstructors) {
			printConstructorInformation(constructor);
		}
		
		try {
			// 获取参数类型为int的构造函数
			Constructor constructor = clz.getConstructor(int.class);
			// 创建Student的实例
			Student student = (Student) constructor.newInstance(10);
			System.out.println("student: " + student.toString());
		} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 打印Constructor信息
	 * @param constructor
	 */
	private static void printConstructorInformation(Constructor constructor) {
		
		// 1. 注解
		// 1.1 getAnnotation(Class) -> 获取指定的注解，如果该Constructor被其注解，则返回该注解，否则返回null。
		Annotation annotationAuthor = constructor.getAnnotation(Author.class);
		if (annotationAuthor != null) {
			System.out.println("该Constructor被Author.class注解");
		} else {
			System.out.println("该Constructor没有被Author.class");
		}
		
		// 1.2 getAnnotations() -> 返回该Constructor上的所有注解。如果没有任何注解，将返回一个空数组。
		Annotation[] annotations = constructor.getAnnotations();
		System.out.println("该Constructor的所有注解：" + Arrays.toString(annotations));
		
		// 2  getDeclaringClass() -> 返回声明此对象的类或接口的Class对象。
		Class declaringClass = constructor.getDeclaringClass();
		System.out.println("declaringClass：" + declaringClass.getName());
		
		// 3. Exception
		// 3.1 getExceptionTypes() -> 返回Class对象的数组，这些对象表示Constructor在执行时抛出的异常类型。
		Class[] exceptionTypes = constructor.getExceptionTypes();
		System.out.println("exceptionTypes：" + Arrays.toString(exceptionTypes));
		
		// 3.2 getGenericExceptionTypes() ->  返回Type对象的数组，这些对象表示Constructor在执行时抛出的异常类型。
		Type[] genericExceptionTypes = constructor.getGenericExceptionTypes();
		System.out.println("genericExceptionTypes：" + Arrays.toString(genericExceptionTypes));
		
		// 4. 参数
		// 4.1 getParameterCount() -> 返回参数个数
		int paramCount = constructor.getParameterCount();
		System.out.println("参数个数：" + paramCount);
		
		// 4.2 getGenericParameterTypes() -> 返回Type数组，这些对象表示Constructor的按声明顺序的形式参数类型。
		Type[] genericParameterTypes = constructor.getGenericParameterTypes();
		System.out.println("genericParameterTypes：" + Arrays.toString(genericParameterTypes));
		
		// 4.3.  getParameterTypes() -> 返回一个Class<?>对象数组，表示参数类型.如果参数类型为泛型，
		// 其Class对象为`java.lang.Object`
		Class[] parameterTypes = constructor.getParameterTypes();
		System.out.println("parameterTypes: " + Arrays.toString(parameterTypes));
		
		// 4.4 getTypeParameters() -> 返回TypeVariable对象的数组，这些对象表示由此GenericDeclaration对象
		// 以声明顺序表示的泛型声明声明的类型变量。

		TypeVariable[] typeParameters = constructor.getTypeParameters();
		System.out.println("typeParameters：" + Arrays.toString(typeParameters));
		
		// 5. 访问权限
		int modifiers = constructor.getModifiers();
		System.out.println("访问权限：" + Modifier.toString(modifiers));
		
		// 6. 名称
		String name = constructor.getName();
		System.out.println("名称：" + name);
		String genericString = constructor.toGenericString();
		System.out.println("genericString：" + genericString);
		
		// 7. 断言
		// 7.1 isVarArgs() -> 判断该Constructor是否采用可变数量的参数，则返回true; 否则返回false。
		System.out.println("isVarArgs()：" + constructor.isVarArgs());
		
		// 7.2 isSynthetic() -> 如果此Constructor是合成构造，则返回true; 否则返回false。
		// synthetic是由编译器引入的字段、方法、类或其他结构，主要用于JVM内部使用.
		System.out.println("isSynthetic()()：" + constructor.isSynthetic());
		
	}
}
